﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;
using IronPython.Runtime;
using IronPython.Hosting;
using Microsoft.Scripting.Hosting;
using Microsoft.Scripting.Runtime;

namespace scifistories
{
    /// <summary>
    /// Kümmert sich um das Aufrufen der Scripte (Python)
    /// </summary>
    public class ScriptManager
    {
        private ScriptScope globalScriptScope;
        private ScriptEngine pyEngine;
        private ScriptRuntime pyRuntime;
        private List<CompiledCode> compiledScripts;
        private List<ScriptScope> scriptScopes;
        private List<string> scriptIDs;

        /// <summary>
        /// Erzeugt eine neue Instanz von ScriptManager
        /// </summary>
        public ScriptManager()
        {
            compiledScripts = new List<CompiledCode>();
            scriptScopes = new List<ScriptScope>();
            scriptIDs = new List<string>();
            pyEngine = Python.CreateEngine();
            globalScriptScope = pyEngine.CreateScope();
            globalScriptScope.SetVariable("ScifiEngine", this);
        }

        /// <summary>
        /// Lädt sämtliche Scripte die in der ScriptList.xml verzeichnet sind
        /// </summary>
        /// <param name="Content"></param>
        public void LoadScripts(ContentManager Content)
        {
            scriptIDs = Content.Load<List<string>>(@"Script\ScriptList");
            foreach (string script in scriptIDs)
            {
                ScriptScope scope = pyEngine.CreateScope();
                scope.SetVariable("ScifiEngine", this);
                ScriptSource source = pyEngine.CreateScriptSourceFromFile(Content.RootDirectory
                + @"\Script\" + script, Encoding.ASCII, Microsoft.Scripting.SourceCodeKind.File);
                CompiledCode compiled = source.Compile();
                scriptScopes.Add(scope);
                compiledScripts.Add(compiled);
            }
        }

        /// <summary>
        /// Gibt den Wert einer globalen Variable zurück
        /// </summary>
        /// <param name="name">Die Variable</param>
        /// <returns></returns>
        public object GetGlobalVar(string name)
        {
            return globalScriptScope.GetVariable(name);
        }

        /// <summary>
        /// Setzt den Wert einer globalen Variable
        /// </summary>
        /// <param name="name">Die Variable</param>
        /// <param name="value">Der Wert</param>
        public void SetGlobalVar(string name, object value)
        {
            globalScriptScope.SetVariable(name, value);
        }

        /// <summary>
        /// Setzt den Wert einer Variable für ein Script
        /// </summary>
        /// <param name="script">Das Script</param>
        /// <param name="name">Die Variable</param>
        /// <param name="value">Der Wert</param>
        public void SetVar(string script, string name, object value)
        {
            for (int i = 0; i < scriptIDs.Count; i++)
            {
                if (scriptIDs[i] == script)
                {
                    scriptScopes[i].SetVariable(name, value);
                }
            }
        }

        /// <summary>
        /// Holt den Wert einer Variable für ein Script
        /// </summary>
        /// <param name="script">Das Script</param>
        /// <param name="name">Die Variable</param>
        /// <returns></returns>
        public object GetVar(string script, string name)
        {
            for (int i = 0; i < scriptIDs.Count; i++)
            {
                if (scriptIDs[i] == script)
                {
                    return scriptScopes[i].GetVariable(name);
                }
            }
            return null;
        }

        /// <summary>
        /// Führt ein Script aus
        /// </summary>
        /// <param name="script">Das Script</param>
        public void RunScript(string script)
        {
            if (!script.Contains(".py"))
                script += ".py";
            for (int i = 0; i < scriptIDs.Count; i++)
            {
                compiledScripts[i].Execute(scriptScopes[i]);
            }
        }
    }
}
